feat(kernel): route kernel logging through the driver log level + correlate#401
Merged
mani-mathur-arch merged 3 commits intoJul 15, 2026
Merged
Conversation
mani-mathur-arch
force-pushed
the
mani/sea-kernel-richer-tls
branch
from
July 14, 2026 15:36
96ba29c to
ab90eff
Compare
mani-mathur-arch
force-pushed
the
mani/sea-kernel-log-unify
branch
from
July 14, 2026 15:36
ea1378e to
558f46c
Compare
mani-mathur-arch
force-pushed
the
mani/sea-kernel-richer-tls
branch
from
July 14, 2026 18:42
ab90eff to
0abfb38
Compare
mani-mathur-arch
force-pushed
the
mani/sea-kernel-log-unify
branch
from
July 14, 2026 18:42
558f46c to
ba7b5d9
Compare
mani-mathur-arch
force-pushed
the
mani/sea-kernel-richer-tls
branch
from
July 14, 2026 18:48
0abfb38 to
89c9b36
Compare
mani-mathur-arch
force-pushed
the
mani/sea-kernel-log-unify
branch
from
July 14, 2026 18:48
ba7b5d9 to
2922c72
Compare
mani-mathur-arch
force-pushed
the
mani/sea-kernel-richer-tls
branch
from
July 14, 2026 18:53
89c9b36 to
b147d0e
Compare
mani-mathur-arch
force-pushed
the
mani/sea-kernel-log-unify
branch
from
July 14, 2026 18:53
2922c72 to
4b7b202
Compare
Collaborator
Author
There was a problem hiding this comment.
The main theme is that the Go binding logs now follow the live driver logger, but the Rust subscriber remains process-wide/first-call-wins and stderr-only, so the public logging contract should be tightened or the implementation needs a stronger sink/level API.
mani-mathur-arch
added a commit
that referenced
this pull request
Jul 15, 2026
Address the review comments on #401 — the Go binding logs now follow the live driver logger, but the Rust subscriber is process-wide/first-call-wins and stderr-only, so several "one unified knob" claims were stronger than the implementation. Fixes, all in the kernel backend (databricks_kernel tag; the default pure-Go build is unaffected): - doc.go: Rust logs are stderr-only and NOT routed through logger.SetLogOutput; Rust verbosity is fixed at the first kernel session (set the level before the first connection); "each line carries connId/corrId/queryId" softened to request-scoped lines where a ctx is in scope (bindParams / operation teardown stay uncorrelated). - cgo.go: kernelLogLevel maps FatalLevel/PanicLevel -> OFF (not ERROR), so the Rust subscriber is never louder than the driver the user configured — at driver=fatal the Go side suppresses even Error() lines. Tightened the initKernelLogging comment to state the first-session level sampling and the stderr-only sink, and dropped the inaccurate "only installed when the level is at or below the threshold" sentence. - kernel_test.go: TestKernelLogLevel updated for fatal/panic->OFF; new TestKernelLogCtxEmitsCorrelation captures logger output at debug level and asserts klogCtx emits the message + connId/corrId/queryId, then asserts silence at warn — the positive-behavior half the alloc test can't see. Verified: CGO_ENABLED=0 build+vet+test green; CGO_ENABLED=1 -tags databricks_kernel build+vet green, kernel package tests pass (incl. all three log tests). Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
mani-mathur-arch
added a commit
that referenced
this pull request
Jul 15, 2026
Follow-up to the #401 review (finding 5, thread on kernel_test.go): the level- resolution logic initKernelLogging feeds to kernel_init_logging was documented but not tested. Extract the pure decision so it can be pinned by CI without cgo. - New untagged logging_level.go holds kernelLogLevel (moved out of cgo.go) and a new resolveKernelLogArg() (level string, useNULL bool): the NULL-on- DBSQL_KERNEL_DEBUG override vs the mapped driver level. Mirrors the existing errors_classify.go pattern (pure logic, no build tag) so its tests run under CGO_ENABLED=0. cgo.go's initKernelLogging is now a thin caller of it. - New untagged logging_level_test.go: TestKernelLogLevel (moved) + new TestResolveKernelLogArg, which pins the two invariants the PR justifies in prose — DBSQL_KERNEL_DEBUG (non-empty) yields useNULL=true so the kernel honors RUST_LOG, and otherwise the driver level is mapped in (incl. fatal→OFF). Empty value is treated as unset. - Drops the now-unused os import from cgo.go and zerolog from kernel_test.go. Not covered (documented, cost/value flips): that the string is actually handed to C.kernel_init_logging and the sync.Once first-call-wins — asserting those needs a function-pointer seam over the cgo call plus resetting a package global, to test one assignment + stdlib sync.Once. Verified: CGO_ENABLED=0 build+vet+test green (both new tests run here); CGO_ENABLED=1 -tags databricks_kernel build+vet green, all four log tests pass. Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
mani-mathur-arch
marked this pull request as ready for review
July 15, 2026 08:39
mani-mathur-arch
added a commit
that referenced
this pull request
Jul 15, 2026
Address the review comments on #401 — the Go binding logs now follow the live driver logger, but the Rust subscriber is process-wide/first-call-wins and stderr-only, so several "one unified knob" claims were stronger than the implementation. Fixes, all in the kernel backend (databricks_kernel tag; the default pure-Go build is unaffected): - doc.go: Rust logs are stderr-only and NOT routed through logger.SetLogOutput; Rust verbosity is fixed at the first kernel session (set the level before the first connection); "each line carries connId/corrId/queryId" softened to request-scoped lines where a ctx is in scope (bindParams / operation teardown stay uncorrelated). - cgo.go: kernelLogLevel maps FatalLevel/PanicLevel -> OFF (not ERROR), so the Rust subscriber is never louder than the driver the user configured — at driver=fatal the Go side suppresses even Error() lines. Tightened the initKernelLogging comment to state the first-session level sampling and the stderr-only sink, and dropped the inaccurate "only installed when the level is at or below the threshold" sentence. - kernel_test.go: TestKernelLogLevel updated for fatal/panic->OFF; new TestKernelLogCtxEmitsCorrelation captures logger output at debug level and asserts klogCtx emits the message + connId/corrId/queryId, then asserts silence at warn — the positive-behavior half the alloc test can't see. Verified: CGO_ENABLED=0 build+vet+test green; CGO_ENABLED=1 -tags databricks_kernel build+vet green, kernel package tests pass (incl. all three log tests). Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
mani-mathur-arch
added a commit
that referenced
this pull request
Jul 15, 2026
Follow-up to the #401 review (finding 5, thread on kernel_test.go): the level- resolution logic initKernelLogging feeds to kernel_init_logging was documented but not tested. Extract the pure decision so it can be pinned by CI without cgo. - New untagged logging_level.go holds kernelLogLevel (moved out of cgo.go) and a new resolveKernelLogArg() (level string, useNULL bool): the NULL-on- DBSQL_KERNEL_DEBUG override vs the mapped driver level. Mirrors the existing errors_classify.go pattern (pure logic, no build tag) so its tests run under CGO_ENABLED=0. cgo.go's initKernelLogging is now a thin caller of it. - New untagged logging_level_test.go: TestKernelLogLevel (moved) + new TestResolveKernelLogArg, which pins the two invariants the PR justifies in prose — DBSQL_KERNEL_DEBUG (non-empty) yields useNULL=true so the kernel honors RUST_LOG, and otherwise the driver level is mapped in (incl. fatal→OFF). Empty value is treated as unset. - Drops the now-unused os import from cgo.go and zerolog from kernel_test.go. Not covered (documented, cost/value flips): that the string is actually handed to C.kernel_init_logging and the sync.Once first-call-wins — asserting those needs a function-pointer seam over the cgo call plus resetting a package global, to test one assignment + stdlib sync.Once. Verified: CGO_ENABLED=0 build+vet+test green (both new tests run here); CGO_ENABLED=1 -tags databricks_kernel build+vet green, all four log tests pass. Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
mani-mathur-arch
force-pushed
the
mani/sea-kernel-log-unify
branch
from
July 15, 2026 09:19
ef7e5ec to
752e19b
Compare
mani-mathur-arch
added a commit
that referenced
this pull request
Jul 15, 2026
Address the review comments on #401 — the Go binding logs now follow the live driver logger, but the Rust subscriber is process-wide/first-call-wins and stderr-only, so several "one unified knob" claims were stronger than the implementation. Fixes, all in the kernel backend (databricks_kernel tag; the default pure-Go build is unaffected): - doc.go: Rust logs are stderr-only and NOT routed through logger.SetLogOutput; Rust verbosity is fixed at the first kernel session (set the level before the first connection); "each line carries connId/corrId/queryId" softened to request-scoped lines where a ctx is in scope (bindParams / operation teardown stay uncorrelated). - cgo.go: kernelLogLevel maps FatalLevel/PanicLevel -> OFF (not ERROR), so the Rust subscriber is never louder than the driver the user configured — at driver=fatal the Go side suppresses even Error() lines. Tightened the initKernelLogging comment to state the first-session level sampling and the stderr-only sink, and dropped the inaccurate "only installed when the level is at or below the threshold" sentence. - kernel_test.go: TestKernelLogLevel updated for fatal/panic->OFF; new TestKernelLogCtxEmitsCorrelation captures logger output at debug level and asserts klogCtx emits the message + connId/corrId/queryId, then asserts silence at warn — the positive-behavior half the alloc test can't see. Verified: CGO_ENABLED=0 build+vet+test green; CGO_ENABLED=1 -tags databricks_kernel build+vet green, kernel package tests pass (incl. all three log tests). Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
mani-mathur-arch
added a commit
that referenced
this pull request
Jul 15, 2026
Follow-up to the #401 review (finding 5, thread on kernel_test.go): the level- resolution logic initKernelLogging feeds to kernel_init_logging was documented but not tested. Extract the pure decision so it can be pinned by CI without cgo. - New untagged logging_level.go holds kernelLogLevel (moved out of cgo.go) and a new resolveKernelLogArg() (level string, useNULL bool): the NULL-on- DBSQL_KERNEL_DEBUG override vs the mapped driver level. Mirrors the existing errors_classify.go pattern (pure logic, no build tag) so its tests run under CGO_ENABLED=0. cgo.go's initKernelLogging is now a thin caller of it. - New untagged logging_level_test.go: TestKernelLogLevel (moved) + new TestResolveKernelLogArg, which pins the two invariants the PR justifies in prose — DBSQL_KERNEL_DEBUG (non-empty) yields useNULL=true so the kernel honors RUST_LOG, and otherwise the driver level is mapped in (incl. fatal→OFF). Empty value is treated as unset. - Drops the now-unused os import from cgo.go and zerolog from kernel_test.go. Not covered (documented, cost/value flips): that the string is actually handed to C.kernel_init_logging and the sync.Once first-call-wins — asserting those needs a function-pointer seam over the cgo call plus resetting a package global, to test one assignment + stdlib sync.Once. Verified: CGO_ENABLED=0 build+vet+test green (both new tests run here); CGO_ENABLED=1 -tags databricks_kernel build+vet green, all four log tests pass. Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
mani-mathur-arch
force-pushed
the
mani/sea-kernel-log-unify
branch
from
July 15, 2026 09:48
752e19b to
125eec7
Compare
…relate Unify kernel-backend logging onto the driver's shared logger so the one knob that controls the rest of the driver — DATABRICKS_LOG_LEVEL / dbsql.SetLogLevel — governs it, and each binding line carries the structured connId/corrId/queryId fields that let it be correlated in a multi-connection process. Addresses vikrantpuppala's review on #393 (klog + the kernel Rust subscriber emitted unstructured lines straight to os.Stderr, uncorrelatable and gated on a separate DBSQL_KERNEL_DEBUG rather than the driver log level). Three parts: - Level: klog now emits through logger.Logger.Debug() instead of raw fmt.Fprintf(os.Stderr, ...). A cheap kernelDebugOff() front gate (GetLevel() > Debug) short-circuits before any formatting/allocation, so it stays a true no-op at the default Warn level — including during benchmarks. Replaces the old DBSQL_KERNEL_DEBUG bool + the caller-less KernelDebugEnabled. - Correlation: new klogCtx(ctx, ...) pulls connId/corrId/queryId off ctx via logger.WithContext (the exact idiom the Thrift/conn path uses); the conn layer already stuffs those IDs into ctx before calling the backend. Every hot-path site (execute, nextBatch, newKernelRows, Open/CloseSession) uses it; ctx-less sites degrade to klog. The WithContext allocation is behind the same up-front level gate, so it never runs below Debug. - Kernel Rust logs: initKernelLogging maps the driver level -> the kernel_init_logging level string (kernelLogLevel), so DATABRICKS_LOG_LEVEL drives the kernel's Rust logs too. DBSQL_KERNEL_DEBUG is kept as an advanced override (forces the subscriber on, defers to RUST_LOG for kernel verbosity). Known limitation (documented): the kernel's Rust lines are still plain text and do not yet carry the structured fields — that needs the kernel log-callback ABI (PECOBLR-3654 / K4). Only the Go binding lines are structured today. Tests: TestKernelLogLevel pins the level mapping; TestKernelLogNoAllocWhenOff uses testing.AllocsPerRun to prove klog/klogCtx allocate 0 times at Warn level (guards the hot-path zero-cost guarantee). Closes PECOBLR-3650. Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
Address the review comments on #401 — the Go binding logs now follow the live driver logger, but the Rust subscriber is process-wide/first-call-wins and stderr-only, so several "one unified knob" claims were stronger than the implementation. Fixes, all in the kernel backend (databricks_kernel tag; the default pure-Go build is unaffected): - doc.go: Rust logs are stderr-only and NOT routed through logger.SetLogOutput; Rust verbosity is fixed at the first kernel session (set the level before the first connection); "each line carries connId/corrId/queryId" softened to request-scoped lines where a ctx is in scope (bindParams / operation teardown stay uncorrelated). - cgo.go: kernelLogLevel maps FatalLevel/PanicLevel -> OFF (not ERROR), so the Rust subscriber is never louder than the driver the user configured — at driver=fatal the Go side suppresses even Error() lines. Tightened the initKernelLogging comment to state the first-session level sampling and the stderr-only sink, and dropped the inaccurate "only installed when the level is at or below the threshold" sentence. - kernel_test.go: TestKernelLogLevel updated for fatal/panic->OFF; new TestKernelLogCtxEmitsCorrelation captures logger output at debug level and asserts klogCtx emits the message + connId/corrId/queryId, then asserts silence at warn — the positive-behavior half the alloc test can't see. Verified: CGO_ENABLED=0 build+vet+test green; CGO_ENABLED=1 -tags databricks_kernel build+vet green, kernel package tests pass (incl. all three log tests). Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
Follow-up to the #401 review (finding 5, thread on kernel_test.go): the level- resolution logic initKernelLogging feeds to kernel_init_logging was documented but not tested. Extract the pure decision so it can be pinned by CI without cgo. - New untagged logging_level.go holds kernelLogLevel (moved out of cgo.go) and a new resolveKernelLogArg() (level string, useNULL bool): the NULL-on- DBSQL_KERNEL_DEBUG override vs the mapped driver level. Mirrors the existing errors_classify.go pattern (pure logic, no build tag) so its tests run under CGO_ENABLED=0. cgo.go's initKernelLogging is now a thin caller of it. - New untagged logging_level_test.go: TestKernelLogLevel (moved) + new TestResolveKernelLogArg, which pins the two invariants the PR justifies in prose — DBSQL_KERNEL_DEBUG (non-empty) yields useNULL=true so the kernel honors RUST_LOG, and otherwise the driver level is mapped in (incl. fatal→OFF). Empty value is treated as unset. - Drops the now-unused os import from cgo.go and zerolog from kernel_test.go. Not covered (documented, cost/value flips): that the string is actually handed to C.kernel_init_logging and the sync.Once first-call-wins — asserting those needs a function-pointer seam over the cgo call plus resetting a package global, to test one assignment + stdlib sync.Once. Verified: CGO_ENABLED=0 build+vet+test green (both new tests run here); CGO_ENABLED=1 -tags databricks_kernel build+vet green, all four log tests pass. Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
mani-mathur-arch
force-pushed
the
mani/sea-kernel-richer-tls
branch
from
July 15, 2026 12:39
8c108b4 to
1e6d921
Compare
mani-mathur-arch
force-pushed
the
mani/sea-kernel-log-unify
branch
from
July 15, 2026 12:40
125eec7 to
aa27368
Compare
Base automatically changed from
mani/sea-kernel-richer-tls
to
mani/sea-kernel-consolidated
July 15, 2026 13:48
mani-mathur-arch
merged commit Jul 15, 2026
aa27368
into
mani/sea-kernel-consolidated
5 checks passed
mani-mathur-arch
added a commit
that referenced
this pull request
Jul 15, 2026
Address the review comments on #401 — the Go binding logs now follow the live driver logger, but the Rust subscriber is process-wide/first-call-wins and stderr-only, so several "one unified knob" claims were stronger than the implementation. Fixes, all in the kernel backend (databricks_kernel tag; the default pure-Go build is unaffected): - doc.go: Rust logs are stderr-only and NOT routed through logger.SetLogOutput; Rust verbosity is fixed at the first kernel session (set the level before the first connection); "each line carries connId/corrId/queryId" softened to request-scoped lines where a ctx is in scope (bindParams / operation teardown stay uncorrelated). - cgo.go: kernelLogLevel maps FatalLevel/PanicLevel -> OFF (not ERROR), so the Rust subscriber is never louder than the driver the user configured — at driver=fatal the Go side suppresses even Error() lines. Tightened the initKernelLogging comment to state the first-session level sampling and the stderr-only sink, and dropped the inaccurate "only installed when the level is at or below the threshold" sentence. - kernel_test.go: TestKernelLogLevel updated for fatal/panic->OFF; new TestKernelLogCtxEmitsCorrelation captures logger output at debug level and asserts klogCtx emits the message + connId/corrId/queryId, then asserts silence at warn — the positive-behavior half the alloc test can't see. Verified: CGO_ENABLED=0 build+vet+test green; CGO_ENABLED=1 -tags databricks_kernel build+vet green, kernel package tests pass (incl. all three log tests). Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
mani-mathur-arch
added a commit
that referenced
this pull request
Jul 15, 2026
Follow-up to the #401 review (finding 5, thread on kernel_test.go): the level- resolution logic initKernelLogging feeds to kernel_init_logging was documented but not tested. Extract the pure decision so it can be pinned by CI without cgo. - New untagged logging_level.go holds kernelLogLevel (moved out of cgo.go) and a new resolveKernelLogArg() (level string, useNULL bool): the NULL-on- DBSQL_KERNEL_DEBUG override vs the mapped driver level. Mirrors the existing errors_classify.go pattern (pure logic, no build tag) so its tests run under CGO_ENABLED=0. cgo.go's initKernelLogging is now a thin caller of it. - New untagged logging_level_test.go: TestKernelLogLevel (moved) + new TestResolveKernelLogArg, which pins the two invariants the PR justifies in prose — DBSQL_KERNEL_DEBUG (non-empty) yields useNULL=true so the kernel honors RUST_LOG, and otherwise the driver level is mapped in (incl. fatal→OFF). Empty value is treated as unset. - Drops the now-unused os import from cgo.go and zerolog from kernel_test.go. Not covered (documented, cost/value flips): that the string is actually handed to C.kernel_init_logging and the sync.Once first-call-wins — asserting those needs a function-pointer seam over the cgo call plus resetting a package global, to test one assignment + stdlib sync.Once. Verified: CGO_ENABLED=0 build+vet+test green (both new tests run here); CGO_ENABLED=1 -tags databricks_kernel build+vet green, all four log tests pass. Co-authored-by: Isaac Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
mani-mathur-arch
added a commit
that referenced
this pull request
Jul 17, 2026
…tly workflows for e2e tests (#399) ## What Extends the SEA-via-kernel backend for the Go driver with the full DAIS gap-closure + PuPr feature set: authentication, session setup, type rendering, query execution, telemetry, richer TLS, kernel-log routing, and CI. This PR consolidates what was a 5-PR stack (#400 richer-TLS, #401 log-unify, #402 nightly-e2e, #403 c2-dispatch) into a single reviewable PR. The stack was linear, so the branches were fast-forwarded into this one — every change is preserved as a **distinct, logically-scoped commit** (23 commits), so it reads commit-by-commit rather than as one blob. #400–#403 now show as merged (their commits live here). ## Features **Authentication** - **OAuth M2M / U2M** — the kernel drives its own auth flow from `cfg.Authenticator` (mirroring pyo3/napi). Adds a `kernel.Auth` descriptor + `resolveKernelAuth`, wired through the `set_auth_pat` / `_m2m` / `_u2m` C-ABI setters. `cfg.Authenticator` is the single source of truth (last-writer-wins, matching Thrift). - **Unsupported auth is sentinel-wrapped** — token-provider / external / federated authenticators reject with `%w`-wrapped `ErrNotSupportedByKernel`, the same programmatic-fallback contract every other unsupported kernel option follows. **Session setup** - **Initial namespace** — post-connect `USE CATALOG` / `USE SCHEMA` with identifier quoting (the kernel C ABI has no namespace setter). - **Metric-view metadata** — `config.EffectiveSessionParams()` folds the server conf in backend-neutrally, so the kernel path sends the identical conf Thrift does. **Type rendering** - **INTERVAL** day-time & year-month rendering in `internal/arrowscan` (kernel returns native arrow values; formatted Go-side to the Thrift path's string form). Handles the `math.MinInt64` / `math.MinInt32` negation bound without overflow. - Parity coverage for **TIMESTAMP vs TIMESTAMP_NTZ** and **VARIANT / GEOMETRY** (live-probed on both backends). **Query execution & telemetry** - **Bound query parameters** via the kernel raw-param C ABI (`kernel_statement_bind_parameter`). The positional/named + SQL-NULL/empty-string decision is a pure `paramBindArg` seam, unit-tested under `CGO_ENABLED=0`. - **Kernel errors surfaced as `DBExecutionError`** carrying sqlstate + server query id, so `errors.As` → `SqlState()` / `QueryId()` works on the kernel path. The execute path deliberately reports **non-retryable** (a sent statement may have committed — no double-write), matching Thrift. - **Server query id** via a real `StatementID()` accessor (`kernel_executed_statement_query_id`), threaded into EXECUTE_STATEMENT telemetry, plus CLOSE_STATEMENT telemetry on the result-read path. - **Cancelled execute** evicts a session-fatal conn and preserves the kernel error metadata (multi-`%w`: `errors.Is(DeadlineExceeded)` AND `errors.As(*KernelError)` both hold). **Richer TLS (Go options)** - CA-bundle + independent hostname-skip setters mapped to the kernel's own TLS knobs (defensive PEM copy; the wholesale custom `WithTransport` stays rejected). **Kernel logging** - Kernel log output routed through the driver log level with connId/corrId/queryId correlation; allocation-free above Debug (guards the Arrow-batch hot path). - **scope note (please read before flagging):** - This unifies the *control knob*, not the *sink*, and that boundary is intentional. `DATABRICKS_LOG_LEVEL`/`SetLogLevel` now drives both the Go binding lines and the kernel's Rust lines from one level. But they stay two physical streams: Go lines go through `logger.Logger` (and honor `logger.SetLogOutput`), while the kernel's Rust lines go straight to stderr — the kernel C ABI exposes **no sink/callback hook**, so there is currently no way to route them through the Go logger. Consequences a reviewer will notice, all expected: - A custom `SetLogOutput`/file captures only the Go lines; Rust lines stay on stderr. - With the default sink both land on stderr but only *race* there — not a single ordered, merged stream. - The Rust subscriber's level is sampled once, at the first kernel connect. Fully merging both into one ordered sink requires a kernel log callback and is tracked separately (<TICKET>); it's out of scope here because it's a kernel-side ABI change, not a driver one. **CI** - A scheduled + dispatchable **nightly E2E** workflow that runs the credential-gated e2e + Thrift-vs-kernel parity suites against a real warehouse (the ordinary CI injects no warehouse secrets, so those tests otherwise skip). SEA-via-kernel integration leg gated behind a kernel label. ## Notable behavior - Bound query parameters are now supported (previously rejected at connect). - **Staging operations remain rejected** — the kernel path can't perform the local file transfer and the C ABI surfaces no staging signal. ## Testing - **Default pure-Go** (`CGO_ENABLED=0`): `go build` / `go vet` / `go test ./...` — 24 packages ok. - **Tagged kernel path** (`CGO_ENABLED=1 -tags databricks_kernel`, linked against a locally-built kernel `.a` at `KERNEL_REV`): 24 packages ok. - **Live e2e + parity** against a real warehouse: all pass — data types (incl. variant/geometry/decimal), NTZ, params-vs-Thrift (10/10), CloudFetch, cancellation, connection pool (40/40), StatementID, initial namespace, and **M2M** (OAuth client-credentials). - `gofmt` clean; Isaac Review clean (0 final comments). ## Merge gate - **Re-pin `KERNEL_REV` at merge time.** It currently points at the kernel dependency's PR-head SHA (GC-able once that kernel change merges); bump it to the resulting kernel `main` SHA, re-sync the cgo drift assertions in `cgo.go` if any signatures changed, and run `make test-kernel` against the new rev. This pull request and its description were written by Isaac. --------- Signed-off-by: Mani Kaustubh Mathur <mani.mathur@databricks.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context for reviewers
Part of the SEA-via-kernel backend for the Go driver (an alternative to Thrift that talks to Databricks SQL through the Rust
databricks-sql-kernelstatic library over a C ABI, behind thedatabricks_kernelbuild tag; the default pure-Go build is unaffected). This PR makes the kernel backend's logging behave like the rest of the driver's.Stack position:
Where to focus review: the hot-path allocation guard (see the review note below) — this is the load-bearing correctness point, since a debug log that allocates when disabled would regress the per-batch fetch path.
What
Unify kernel-backend logging onto the driver's shared logger, so the one knob that controls the rest of the driver —
DATABRICKS_LOG_LEVEL/dbsql.SetLogLevel— governs it, and each binding line carries the structuredconnId/corrId/queryIdfields that let it be correlated in a multi-connection process.Addresses @vikrantpuppala's review comment:
klogand the kernel Rust subscriber emitted unstructured lines straight toos.Stderr— uncorrelatable, and gated on a separateDBSQL_KERNEL_DEBUGrather than the driver log level.Closes PECOBLR-3650.
Three parts (the ticket was scoped as one, the review surfaced two more)
The JIRA row was originally just "route kernel debug logging through
DATABRICKS_LOG_LEVELinstead ofDBSQL_KERNEL_DEBUG." The review raised a second, distinct problem (unstructured, uncorrelatable lines), so the complete fix is three parts:klognow emits throughlogger.Logger.Debug()instead of rawfmt.Fprintf(os.Stderr, ...). A cheapkernelDebugOff()front gate (GetLevel() > Debug) short-circuits before any formatting/allocation, so it stays a true no-op at the default Warn level, benchmarks included. Replaces the oldDBSQL_KERNEL_DEBUGbool and the caller-lessKernelDebugEnabled.klogCtx(ctx, ...)pullsconnId/corrId/queryIdoff ctx vialogger.WithContext(the exact idiom the Thrift/conn path uses atconnection.go:139); the conn layer already stuffs those IDs into ctx before calling the backend. Every hot-path site (execute,nextBatch,newKernelRows,Open/CloseSession) uses it; ctx-less sites (bindParams,kernelOp.close,lastError) degrade toklog. TheWithContextallocation is behind the same up-front level gate, so it never runs below Debug.initKernelLoggingmaps the driver's zerolog level → thekernel_init_logginglevel string (kernelLogLevel), soDATABRICKS_LOG_LEVELdrives the kernel's Rust logs too. The accepted level strings were verified against kernel source (src/c_abi/session.rs; a bad level safely falls back toRUST_LOG).DBSQL_KERNEL_DEBUGis kept as an advanced override (forces the subscriber on, defers toRUST_LOGfor kernel-only verbosity).Why
DBSQL_KERNEL_DEBUGis retained (not justRUST_LOG)The kernel reads
RUST_LOGonly when it's passed a NULL level — the moment a concrete level is supplied it builds the filter from that and never consultsRUST_LOG(src/logging.rs). Since the normal path now always passes the mapped driver level,RUST_LOGalone is inert;DBSQL_KERNEL_DEBUGis the one switch that makes the Go side pass NULL, unlockingRUST_LOG. That buys two things the driver level structurally can't: a kernel-Rust verbosity decoupled from the driver level, and per-target filtering — including the HTTP stack (RUST_LOG=debug→hyper/reqwest), which the driver-level mapping (scoped todatabricks::sql::kernel) never surfaces.Known limitation (documented)
The kernel's Rust log lines are still plain text — they do not yet carry the structured fields, because they're emitted inside Rust. Fully structuring them needs the kernel log-callback ABI (PECOBLR-3654 / K4). Only the Go binding lines are structured today.
doc.gostates this.Testing
CGO_ENABLED=0and taggedCGO_ENABLED=1 -tags databricks_kernel: build + vet + test — 24 pkg ok, 0 fail each.TestKernelLogLevelpins the zerolog→kernel level mapping (incl. fatal/panic→ERROR, default→WARN).TestKernelLogNoAllocWhenOffusestesting.AllocsPerRunto proveklog/klogCtxallocate 0 times at the default Warn level — the hot-path zero-cost guarantee, kept as a regression guard.Review note (why the alloc guard exists)
Isaac Review, 2 passes: the first pass caught 2 legitimate MAJORs —
klogCtxbuiltlogger.WithContext(which eagerlymake([]byte, 0, 500)s inside zerolog'sWith()) before the.Debug()gate, so it allocated ~500 B per call even at Warn, on the per-batchnextBatchpath.logger.Logger.Debug().Msgf(...)is not allocation-free when off if the arguments themselves allocate — the.Debug()no-op only discards the event, after the arg expressions have already run. Fixed with the up-frontkernelDebugOff()gate + theAllocsPerRunregression test; second pass clean (0/0/0). Two info items filtered: a non-issue nil-ctx path, and a pre-existing global-logger data race that predates this change and affects the Thrift path equally.Stacking
Stacked on #400 (
mani/sea-kernel-richer-tls), which is stacked on #399. NoKERNEL_REVchange (inherits #399's pin).This pull request and its description were written by Isaac.